﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Infrastructure.DataTypes;

namespace Infrastructure
{
    public class User<R> where R : ICountable,new()//Data set now only for Icountable 
    {
        private string userID;//user id , that's how the user identified in data set
        private Dictionary<Item<R>, R> votes;
        public StatisticAttributes StatisticsAttributes{get; private set;}
        //statistical data on user
        private Dictionary<string, string> m_dDataAttributes;//extra data on user like name,age etc ....

        public User(string ID)
        {
            userID = ID;
            StatisticsAttributes = new StatisticAttributes();
            m_dDataAttributes = new Dictionary<string, string>();
            votes = new Dictionary<Item<R>, R>();
        }
        /// <summary>
        /// get user ID
        /// </summary>
        public string UserID
        {
            get { return userID; }
        }


        /// <summary>
        /// get Items and scores for the user
        /// </summary>
        public Dictionary<Item<R>, R> Votes
        {
            get { return votes; }
        }
        /// <summary>
        /// get user data attributes like user name
        /// </summary>
        public Dictionary<string, string> DataAttributes 
        {
            get { return m_dDataAttributes; } 
        }


        /// <summary>
        /// set non numerical data on item 
        /// </summary>
        /// <param name="atr">Name of data</param>
        /// <param name="value">Value of data</param>
        public void SetDataAttribute(string atr, string value)
        {
            if (m_dDataAttributes.ContainsKey(atr))
            {
                m_dDataAttributes[atr] = value;
            }
            else
            {
                m_dDataAttributes.Add(atr, value);
            }
        }

        /// <summary>
        /// add rating to votes, of user for given item
        /// </summary>
        /// <param name="item"></param>
        /// <param name="score"></param>
        public void AddScore(Item<R> item, R score)
        {
            if (votes.ContainsKey(item))
            {
                votes[item] = score;
            }
            else
            {
                votes.Add(item, score);
            }
        }

        /// <summary>
        /// returns the rating given to item by this user. In case of non rated item -returns null.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public R getRating(Item<R> item)
        {
            if (item == null || !votes.ContainsKey(item))
                return new R();

            return votes[item];
        }

        /// <summary>
        /// returns true if user has rated the item.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool hasRating(Item<R> item)
        {
            return this.Votes.ContainsKey(item);
        }

        /// <summary>
        /// Hides a set of test items to be guessed.
        /// Returns a new user which does not contain the set of test items.
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public User<R> Split(List<Item<R>> lHidden)
        {
            Random random = new Random();
            User<R> uTrain = new User<R>(userID);
            int scoreCounter = 0;
            double totalScores = 0;
            foreach (Item<R> i in votes.Keys)
            {
                int rnd = random.Next(100);
                if (rnd > 50)
                {
                    uTrain.AddScore(i, votes[i]);
                    scoreCounter++;
                    totalScores += votes[i];
                }
                else
                {
                    lHidden.Add(i);
                }
                uTrain.StatisticsAttributes.AverageRating = totalScores / scoreCounter;
                return uTrain;
            }

            //TODO: your code here!
            //important - remeber to set the AverageRating on the SatatisticsAttribute of the new user

            return uTrain;
        }
       
        class UseEqualityComparer : IEqualityComparer<User<R>>
        {

            #region IEqualityComparer<User<R>> Members

            public bool Equals(User<R> x, User<R> y)
            {
                return x.UserID.Equals(y.UserID);
            }

            public int GetHashCode(User<R> obj)
            {
                throw new NotImplementedException();
            }

            #endregion

        }
    }

    

}
